package com.newx.limit.handler.interceptor;

import com.newx.limit.annotation.AccessLimit;
import com.newx.limit.condition.LimitAspectCondition;
import com.newx.limit.config.BrushConfig;
import com.newx.limit.constant.ConfigConstant;
import com.newx.limit.handler.exeption.NewxLimitException;
import io.netty.util.internal.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.concurrent.TimeUnit;

/**
 * @Classname BrushInterceptor
 * @Description TODO
 * @Date 2024/1/20 17:29
 * @Created by yxl
 */
@Slf4j
//@Component
//@Conditional(LimitAspectCondition.class)
public class BrushInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private BrushConfig brushConfig;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        log.info("进入自定义防刷拦截器");
        String ip = request.getRemoteAddr();
        String uri = request.getRequestURI();
        Assert.notNull(brushConfig.getSeconds(), "自定义-防刷-时间未配置");
        Assert.notNull(brushConfig.getMaxCount(), "自定义-防刷-次数未配置");
        Assert.notNull(brushConfig.getBrush(), "自定义-防刷-开关未配置");
        Assert.notNull(brushConfig.getType(), "自定义-防刷-类型未配置");
        Assert.notNull(brushConfig.getNeedLogin(), "自定义-防刷-是否需要登录未配置");
        String brush = brushConfig.getBrush();
        String type = brushConfig.getType();
        if(!type.equals("custom")){
            return true;
        }
        // 所有接口需要防刷
        if(brush.equals("all")){
            //判断请求是否属于方法的请求
            if(handler instanceof HandlerMethod){
                HandlerMethod hm = (HandlerMethod) handler;
                //获取方法中的注解,看是否有该注解
                AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
                if(accessLimit == null){
                    //如果需要登录
                    if(brushConfig.getNeedLogin()){
                        //获取登录的session进行判断
                        //.....
                        //key+=""+"1";  //这里假设用户是1,项目中是动态获取的userId
                        log.info("需要登录。。。。。。");
                    }
                    String key = ConfigConstant.NEWX_LIMIT_CUSTOM_BRUSH_KEY_PRE + ip + "_" + uri;
                    String objCount = redisTemplate.opsForValue().get(key);
                    int count = ObjectUtils.isEmpty(objCount) ? 0 : Integer.parseInt(objCount);
                    if (count >= brushConfig.getMaxCount()) { // 如果请求次数超过 10 次，则拒绝请求
                        //render(response,"您操作太频繁啦"); //这里的CodeMsg是一个返回参数
                        throw new NewxLimitException("您操作太频繁了");
                    }else{
                        // 将请求次数加 1 并保存到 Redis 中，过期时间为 【seconds】 秒
                        RedisAtomicInteger counter = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory());
                        counter.expire(brushConfig.getSeconds(),TimeUnit.SECONDS);
                        counter.incrementAndGet();
                    }
                }else{
                    int seconds = accessLimit.seconds();
                    int maxCount = accessLimit.maxCount();
                    boolean login = accessLimit.needLogin();
                    //如果需要登录
                    if(login){
                        //获取登录的session进行判断
                        //.....
                        //key+=""+"1";  //这里假设用户是1,项目中是动态获取的userId
                        log.info("需要登录。。。。。。");
                    }
                    String key = ConfigConstant.NEWX_LIMIT_CUSTOM_BRUSH_KEY_PRE + ip + "_" + uri;
                    String objCount = redisTemplate.opsForValue().get(key);
                    int count = ObjectUtils.isEmpty(objCount) ? 0 : Integer.parseInt(objCount);
                    if (count >= maxCount) { // 如果请求次数超过 10 次，则拒绝请求
                        //render(response,"超出访问次数"); //这里的CodeMsg是一个返回参数
                        throw new NewxLimitException("您操作太频繁了");
                    }else{
                        // 将请求次数加 1 并保存到 Redis 中，过期时间为 【seconds】 秒
                        RedisAtomicInteger counter = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory());
                        counter.expire(brushConfig.getSeconds(),TimeUnit.SECONDS);
                        counter.incrementAndGet();
                    }
                }
            }
        }
        // 部分接口需要防刷
        if(brush.equals("part")){
            //判断请求是否属于方法的请求
            if(handler instanceof HandlerMethod){
                HandlerMethod hm = (HandlerMethod) handler;
                //获取方法中的注解,看是否有该注解
                AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
                if(accessLimit == null){
                    return true;
                }
                int seconds = accessLimit.seconds();
                int maxCount = accessLimit.maxCount();
                boolean login = accessLimit.needLogin();
                //如果需要登录
                if(login){
                    //获取登录的session进行判断
                    //.....
                    //key+=""+"1";  //这里假设用户是1,项目中是动态获取的userId
                    log.info("需要登录。。。。。。");
                }
                String key = ConfigConstant.NEWX_LIMIT_CUSTOM_BRUSH_KEY_PRE + ip + "_" + uri;
                String objCount = redisTemplate.opsForValue().get(key);
                int count = ObjectUtils.isEmpty(objCount) ? 0 : Integer.parseInt(objCount);
                if (count >= maxCount) { // 如果请求次数超过 10 次，则拒绝请求
                    //render(response,"超出访问次数"); //这里的CodeMsg是一个返回参数
                    throw new NewxLimitException("您操作太频繁了");
                }else{
                    // 将请求次数加 1 并保存到 Redis 中，过期时间为 【seconds】 秒
                    RedisAtomicInteger counter = new RedisAtomicInteger(key, redisTemplate.getConnectionFactory());
                    counter.expire(brushConfig.getSeconds(),TimeUnit.SECONDS);
                    counter.incrementAndGet();
                }
            }
        }
        return true;
    }

//    private void render(HttpServletResponse response, String msg)throws Exception {
//        response.setContentType("application/json;charset=UTF-8");
//        OutputStream out = response.getOutputStream();
//        String str  = JSON.toJSONString(CommonResult.error(msg));
//        out.write(str.getBytes("UTF-8"));
//        out.flush();
//        out.close();
//    }
}
